package com.mrd.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashSet;

public class ModelPrinter {

    public static String getInfo(Object object, String subName) {
        StringBuffer output = getObjectInfo(object, subName);
        if (output == null) {
            output = new StringBuffer();
            return "null";
        }
        return output.toString();
    }

    public static void print1(Object obj) {
        StringBuffer output = getObjectInfo(obj, "");
        if (output == null) {
            output = new StringBuffer();
            output.append("null\n");
        }
        System.out.println(output.toString());
    }

    /**
     * @return 可能为空
     */
    private static StringBuffer getObjectInfo(Object obj, String subName) {
        StringBuffer output = new StringBuffer();
        if (obj == null) {
            return null;
        }
        String className = obj.getClass().getName();
        output.append(className + "\t====对象开始打印====\n");
        if (obj instanceof ArrayList) {
            @SuppressWarnings("rawtypes")
            ArrayList list = (ArrayList) obj;
            output.append("size:\t" + list.size() + "\n");
            output.append(className + "\t....对象打印结束....\n");
            return output;
        }
        Method[] methods = obj.getClass().getDeclaredMethods();
        // obj.getClass().getFields(); //获取public成员变量

        Method[] superMethods = null;
        // output.append("superclass:\t" + obj.getClass().getSuperclass().getName() + "\n");
        if (!obj.getClass().getSuperclass().getName().equals("java.lang.Object")) {
            superMethods = obj.getClass().getSuperclass().getDeclaredMethods();
        }
        for (Method method : methods) {
            invokeMethod(method, obj, output);
        }

        if (superMethods != null && superMethods.length > 0) {
            output.append("****value in super class****\n");
            for (Method method : superMethods) {
                invokeMethod(method, obj, output);
            }
        }

        output.append(subName + " : " + className + "\t....对象打印结束....\n");
        return output;
    }

    private static void invokeMethod(Method method, Object invokeObject, StringBuffer output) {
        if (method.getModifiers() != Modifier.PUBLIC) {
            return;
        }
        String mName = method.getName();
        int tempIndex = mName.indexOf("get");
        if (tempIndex != -1 && method.getParameterTypes().length == 0) {
            // System.out.print(method.getName() + " | " + method.getParameterTypes().length);
            Object result = null;
            try {
                result = method.invoke(invokeObject, new Object[]{});
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            String outName = mName.substring(tempIndex + 3);

            if (result != null) {
                // System.out.println("\tresult:\t" + result.getClass().getName());
            } else {
                // System.out.println("\tresult:\tnull");
            }
            String resultClassName = result == null ? "" : result.getClass().getName();
            if (null != result
                    && (resultClassName.equals("org.hibernate.collection.PersistentBag") || resultClassName
                    .equals("org.hibernate.collection.PersistentSet"))) {
                output.append(outName + " : " + method.getGenericReturnType() + "\n");
            } else {
                output.append(outName + " : " + objectToString(result, outName) + "\n");
            }
        }
    }

    private static HashSet<Object> objectSet = new HashSet<Object>();

    private static HashSet<String> exceptedClassSet = new HashSet<String>();

    static {
        exceptedClassSet.add("java.lang.String");
        exceptedClassSet.add("java.sql.Timestamp");
        exceptedClassSet.add("java.util.Date");
        exceptedClassSet.add("java.lang.Long");
        exceptedClassSet.add("java.lang.Integer");
        exceptedClassSet.add("java.lang.Double");
        exceptedClassSet.add("java.lang.Float");
    }

    private static String objectToString(Object obj, String subName) {
        if (obj == null) {
            return null;
        }
        if (exceptedClassSet.contains(obj.getClass().getName())) {
            return obj.toString();
        } else {
            if (objectSet.contains(obj)) {
                return "break\n";
            } else {
                objectSet.add(obj);
                return getInfo(obj, subName);
            }
        }
    }
}
